using AutoMapper;
using B.S.Databasic.Api.Read.Application.Command.Role;
using B.S.Databasic.Domain.RBAC;
using B.S.Databasic.ErrorCode;
using B.S.Databasic.Infrastructure.Interface;
using MediatR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace B.S.Databasic.Api.Read.Application.Handler.Role
{
    public class GetRolePageHandler : IRequestHandler<GetRolePageCommand, ApiPageing<RoleDto>>
    {
        private readonly IBaseRepository<RoleModel> _roleRepo;
        private readonly IBaseRepository<PermissionRoleModel> _rolePermissionRepo;
        private readonly IBaseRepository<PermissionModel> _permissionRepo;
        private readonly IMapper _mapper;

        public GetRolePageHandler(
            IBaseRepository<RoleModel> roleRepo,
            IBaseRepository<PermissionRoleModel> rolePermissionRepo,
            IBaseRepository<PermissionModel> permissionRepo,
            IMapper mapper)
        {
            _roleRepo = roleRepo;
            _rolePermissionRepo = rolePermissionRepo;
            _permissionRepo = permissionRepo;
            _mapper = mapper;
        }

        public async Task<ApiPageing<RoleDto>> Handle(GetRolePageCommand request, CancellationToken cancellationToken)
        {
            var res = new ApiPageing<RoleDto>();
            var roles = _roleRepo.GetAll().Where(x => !x.IsDeleted);
            if (!string.IsNullOrEmpty(request.RoleName))
            {
                roles = roles.Where(x => x.RoleName.Contains(request.RoleName));
            }
            res.TotaCount = roles.Count();
            res.TotaPage = (int)Math.Ceiling(res.TotaCount * 1.0 / request.Size);

            // 使用LINQ联表一次性查出分页数据和权限名
            var query = from role in roles
                        join rp in _rolePermissionRepo.GetAll().Where(rp => !rp.IsDeleted) on role.Id equals rp.RoleId into grp
                        from rp in grp.DefaultIfEmpty()
                        join p in _permissionRepo.GetAll().Where(p => !p.IsDeleted) on rp.PermissionId equals p.Id into pgrp
                        from p in pgrp.DefaultIfEmpty()
                        select new { role, rp, p };

            var grouped = query
                .GroupBy(x => x.role)
                .Select(g => new RoleDto
                {
                    Id = g.Key.Id,
                    RoleName = g.Key.RoleName,
                    PermissionIds = g.Where(x => x.rp != null).Select(x => x.rp.PermissionId).ToList(),
                    PermissionNames = g.Where(x => x.p != null).Select(x => x.p.PermissionName).ToList(),
                    CreateTime = g.Key.CreateTime,
                    IsState = g.Key.IsState,
                });

            res.PageData = grouped
                .OrderByDescending(x => x.CreateTime)
                .Skip((request.Index - 1) * request.Size)
                .Take(request.Size)
                .ToList();

            res.Msg = "查询角色列表成功!";
            res.Code = ApiEnum.Success;
            return await Task.FromResult(res);
        }
    }
}